package com.cloudspace.jindun;

import android.app.ActivityManager;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.support.multidex.MultiDex;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.Display;

import com.android.volley.error.VolleyError;
import com.cloudspace.jindun.config.Configs;
import com.cloudspace.jindun.constants.Constants;
import com.cloudspace.jindun.dao.DaoMaster;
import com.cloudspace.jindun.dao.DaoSession;
import com.cloudspace.jindun.dao.LoginUser;
import com.cloudspace.jindun.log.APPLog;
import com.cloudspace.jindun.manager.MessageNumberManager;
import com.cloudspace.jindun.manager.UserManager;
import com.cloudspace.jindun.message.InfoMessage;
import com.cloudspace.jindun.message.InfoMessageItemProvider;
import com.cloudspace.jindun.model.User;
import com.cloudspace.jindun.network.api.API;
import com.cloudspace.jindun.network.base.ApiCallback;
import com.cloudspace.jindun.network.url.YXHttpUrl;
import com.cloudspace.jindun.rongyun.MyExtensionModule;
import com.cloudspace.jindun.update.UpdateInfo;
import com.cloudspace.jindun.update.UpdateInfoResult;
import com.cloudspace.jindun.user.UserSessionManager;
import com.cloudspace.jindun.utils.ActivityUtil;
import com.cloudspace.jindun.utils.AppPreferences;
import com.cloudspace.jindun.utils.FileUtil;
import com.cloudspace.jindun.utils.ObjUtil;
import com.cloudspace.jindun.utils.SharedPreferencesWrapper;
import com.cloudspace.jindun.utils.ToastMaker;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.linphone.LinphoneManager;
import com.linphone.LinphoneService;
import com.zhy.http.okhttp.OkHttpUtils;
import com.zhy.http.okhttp.callback.StringCallback;

import org.apache.http.HttpStatus;

import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import cn.jpush.android.api.JPushInterface;
import cn.jpush.android.api.TagAliasCallback;
import io.rong.imkit.DefaultExtensionModule;
import io.rong.imkit.IExtensionModule;
import io.rong.imkit.RongExtensionManager;
import io.rong.imkit.RongIM;
import io.rong.imlib.RongIMClient;
import io.rong.imlib.model.UserInfo;
import okhttp3.Call;
import okhttp3.OkHttpClient;

import static com.cloudspace.jindun.network.url.YXHttpUrl.WD_GRZL;
import static com.cloudspace.jindun.user.UserSessionManager.getCurrentLoginUser;


public class JindunApp extends Application {
    private static final String TAG = JindunApp.class.getSimpleName();

    public static void setApp(JindunApp app) {
        instance = app;
    }

    public static JindunApp getApp() {
        if (instance == null) {
            return instance = new JindunApp();
        }
        return instance;
    }

    @Override
    public void onCreate() {
        RongIM.init(this);
        setApp(this);
        super.onCreate();
        doOnCreate(this);

        setupDatabase();

        if (findMyProcessName().equals(getPackageName())){
            checkLinphoneService();
            initOkHttp();
//            checkHeartService();

            checkUpdate();

            connectRongyun();
            JPushInterface.setDebugMode(true);
            JPushInterface.init(this);

            setLocaleLanguage();
        }
    }


    private void connectRongyun() {
        if (getCurrentLoginUser() != null){
            RongIM.connect(getCurrentLoginUser().getCloudToken(), new RongIMClient.ConnectCallback() {

                /**
                 * Token 错误。可以从下面两点检查 1.  Token 是否过期，如果过期您需要向 App Server 重新请求一个新的 Token
                 *                  2.  token 对应的 appKey 和工程里设置的 appKey 是否一致
                 */
                @Override
                public void onTokenIncorrect() {
                    APPLog.tagLog(TAG , " onTokenIncorrect");
                }

                /**
                 * 连接融云成功
                 * @param userid 当前 token 对应的用户 id
                 */
                @Override
                public void onSuccess(String userid) {
                    APPLog.tagLog(TAG , " onSuccess");
                    setMyExtensionModule();

                    setRongyunUserInfoProvider();
                }

                /**
                 * 连接融云失败
                 * @param errorCode 错误码，可到官网 查看错误码对应的注释
                 */
                @Override
                public void onError(RongIMClient.ErrorCode errorCode) {
                    APPLog.tagLog(TAG , " onError");
                }
            });
        }
    }

    private void setRongyunUserInfoProvider() {
        /**
         * 设置用户信息的提供者，供 RongIM 调用获取用户名称和头像信息。
         *
         * @param userInfoProvider 用户信息提供者。
         * @param isCacheUserInfo  设置是否由 IMKit 来缓存用户信息。<br>
         *                         如果 App 提供的 UserInfoProvider
         *                         每次都需要通过网络请求用户数据，而不是将用户数据缓存到本地内存，会影响用户信息的加载速度；<br>
         *                         此时最好将本参数设置为 true，由 IMKit 将用户信息缓存到本地内存中。
         * @see UserInfoProvider
         */
        RongIM.setUserInfoProvider(new RongIM.UserInfoProvider() {

            @Override
            public UserInfo getUserInfo(String userId) {
                getUserInfoFromCSServer(userId);
                return null;//根据 userId 去你的用户系统里查询对应的用户信息返回给融云 SDK。
            }

        }, true);

    }

    private void getUserInfoFromCSServer(String userId) {
        OkHttpUtils.get()
                .url(WD_GRZL + userId)
                .build()
                .execute(new StringCallback() {
                    @Override
                    public void onError(Call call, Exception e, int id) {

                    }

                    @Override
                    public void onResponse(String response, int id) {
                        if (response != null) {
                            Gson gson = new Gson();
                            User user = gson.fromJson(response, User.class);


                            if (!ObjUtil.isEmpty(user) && !ObjUtil.isEmpty(user.getData())){
                                User.UserData data = user.getData();

                                APPLog.zxhLog(TAG + " getUserInfoFromCSServer:" + data.getUserName());
                                UserInfo info = new UserInfo(data.getUserId(),data.getUserName(),
                                        Uri.parse(data.getIconUrl()));
                                RongIM.getInstance().refreshUserInfoCache(info);
                                APPLog.zxhLog(TAG + " refreshUserInfoCache");
                            }


                        }

                    }
                });
    }

    public void setMyExtensionModule() {
        List<IExtensionModule> moduleList = RongExtensionManager.getInstance().getExtensionModules();
        IExtensionModule defaultModule = null;
        if (moduleList != null) {
            for (IExtensionModule module : moduleList) {
                if (module instanceof DefaultExtensionModule) {
                    defaultModule = module;
                    break;
                }
            }
            if (defaultModule != null) {
                RongExtensionManager.getInstance().unregisterExtensionModule(defaultModule);
                RongExtensionManager.getInstance().registerExtensionModule(new MyExtensionModule());
            }
        }

        RongIM.registerMessageType(InfoMessage.class);
        RongIM.getInstance().registerMessageTemplate(new InfoMessageItemProvider());
    }

    private void setLocaleLanguage(){
        Resources resources = getResources();
        DisplayMetrics dm = resources.getDisplayMetrics();
        Configuration config = resources.getConfiguration();
        // 应用用户选择语言
        config.locale = Locale.CHINA;
        resources.updateConfiguration(config, dm);
    }


    private static JindunApp instance;

    public static JindunApp getInstance() {
        return instance;
    }

    public void doOnCreate(Application app) {
        ActivityUtil.init();
        ToastMaker.init(this);
        pre = getSharedPreferences();
    }

    private String findMyProcessName() {
        ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> services = manager.getRunningAppProcesses();
        if (services != null) {
            for (ActivityManager.RunningAppProcessInfo process : services) {
                APPLog.i("app_push", "list process name: " + process.processName + " id: " + process.pid);
                if (process.pid == android.os.Process.myPid()) {
                    return process.processName;
                }
            }
        }
        return "";
    }

    public SharedPreferences getSharedPreferences() {
        if (pre == null) {
            SharedPreferences sp = this.getSharedPreferences(Configs.PRE_NAME,
                    Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE);
            pre = new SharedPreferencesWrapper(sp);
        }
        return pre;
    }

    private Object mSpLock;

    public synchronized Object getSharedPreferenceLock() {
        if (mSpLock == null) {
            mSpLock = new Object();
        }
        return mSpLock;
    }

    private DaoSession daoSession;

    private void setupDatabase() {
        DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "jindun-db", null);
        try {
            SQLiteDatabase db = helper.getWritableDatabase();
            DaoMaster daoMaster = new DaoMaster(db);
            daoSession = daoMaster.newSession();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public DaoSession getDaoSession() {
        return daoSession;
    }

    private static Gson gson;

    public static Gson getGson() {
        if (gson == null) {
            return (new GsonBuilder()).create();
        }
        return gson;
    }

    private int width;
    private int height;
    private int density;

    public int getScreenWidth() {
        return width;
    }

    public static boolean isInitScreenParam = false;

    public void initScreenParams(Display display) {
        if (!isInitScreenParam) {
            isInitScreenParam = true;
            DisplayMetrics metric = new DisplayMetrics();
            display.getMetrics(metric);
            this.width = metric.widthPixels; // 屏幕宽度（像素）
            this.height = metric.heightPixels; // 屏幕高度（像素） metric.heightPixels
            // 包括信息栏
            this.density = metric.densityDpi;
        }
    }

    //运用list来保存们每一个activity是关键
    private List<AppCompatActivity> mList = new LinkedList<AppCompatActivity>();

    // add Activity
    public void addActivity(AppCompatActivity activity) {
        mList.add(activity);
    }

    public void removeActivity(AppCompatActivity activity) {
        mList.remove(activity);
    }

    public SharedPreferences pre;

    public int getScreenHeight() {
        return height;
    }

    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
    }

    public boolean registerSipSuccess() {
        return LinphoneManager.getInstance().isSipAccountOk();
    }

    @Override
    public void onTerminate() {
        super.onTerminate();
        APPLog.d("zxh", "onTerminate");
    }

    private void initOkHttp() {
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(10000L, TimeUnit.MILLISECONDS)
                .readTimeout(10000L, TimeUnit.MILLISECONDS)
                //其他配置
                .build();
        OkHttpUtils.initClient(okHttpClient);
    }

    public boolean skipFirstPage(){
        return !ObjUtil.isEmpty(UserManager.getInstance().queryLoginUser());
    }

    public void checkLinphoneService(){
        if (!LinphoneService.isReady() && !TextUtils.isEmpty(UserSessionManager.getInstance().getSipAccount())) {
            startService(new Intent(Intent.ACTION_MAIN).setClass(this, LinphoneService.class));
        }
    }

//    public void checkHeartService(){
//        if (!HeartService.isReady()){
//            startService(new Intent(Intent.ACTION_MAIN).setClass(this, HeartService.class));
//        }
//    }

    public void setUserInfo(LoginUser user) {
        if (ObjUtil.isEmpty(user)) {
            APPLog.zxhLog(TAG + " user is null");
            return;
        }

        connectRongyun();
        UserSessionManager.getInstance().setRongyunUserInfo(user);
        checkLinphoneService();

        String registrationID = JPushInterface.getRegistrationID(this);

        setJPushId(registrationID);

        //置空当前频道号
        AppPreferences.putString(Constants.USER_LAST_ACTIVE_CHANNEL+
                        UserSessionManager.getInstance().getUserId(),
                "");
        MessageNumberManager.getInstance().clearAllMessage();
    }

    private void setJPushId(String registrationID) {
        if (registrationID != null) {
            upJpushID(YXHttpUrl.LOGIN_JPUSH, UserSessionManager.getInstance().getUserId(), registrationID);
            JPushInterface.setAlias(this, UserSessionManager.getInstance().getUserId(), new TagAliasCallback() {
                @Override
                public void gotResult(int errno, String s, Set<String> set) {
                    if (errno == 0){
                        APPLog.zxhLog(TAG + " JPushInterface.setAlias success:" + s);
                    }else{
                        APPLog.zxhLog(TAG + " JPushInterface.setAlias fail:" + errno + " " + s);
                    }
                }
            });
        }
    }

    private void upJpushID(String url, String userId, String JGRegisterId) {
        OkHttpUtils.post()
                .url(url)
                .addParams("userId",userId)
                .addParams("JGRegisterId",JGRegisterId)
                .build()
                .execute(new StringCallback() {
                    @Override
                    public void onError(Call call, Exception e, int id) {

                    }
                    @Override
                    public void onResponse(String response, int id) {
                    }
                });
    }

    private UpdateInfo updateInfo;

    public UpdateInfo getUpdateInfo(){
        return updateInfo;
    }

    private void checkUpdate(){
        API.getInstance().getUpdateApi().getUpdateInfo(TAG, new ApiCallback<UpdateInfoResult>() {
            @Override
            public void handleResult(UpdateInfoResult result, VolleyError error) {
                if (result != null && result.status == HttpStatus.SC_OK){
                    updateInfo = result.data;
                }
            }
        }.toastActionError());
    }

    public String getLogDir(){
        return FileUtil.getLocalLogPath();
    }
}
